/**
 * 
 */
package it.uniroma3.dia.digraph.algorithm.utility.kouterplanar.outerplanar;

import it.uniroma3.dia.digraph.algorithm.utility.Utility;
import it.uniroma3.dia.digraph.algorithm.utility.kouterplanar.Peeler;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.graphdrawing.graphml.xmlns.GraphType;
import org.graphdrawing.graphml.xmlns.NodeType;

/**
 * Models an outerplanar graph
 * @author Cionzo
 *
 */
public class OuterplanarGraph {
	
	private GraphType graph;
	private List<OuterplanarNode> nodes;
	private Map<String, OuterplanarNode> nodeMap;
	private Map<String, Set<String>> adjacencyMatrix;
	
	/**
	 * Creates a new OuterplanarGraph based on the specified {@link GraphType}
	 * @param graph the graph that this has to be built onto
	 */
	public OuterplanarGraph (GraphType graph){
		this.graph = graph;
		this.adjacencyMatrix = Utility.buildAdjacencyMatrix(graph);
		this.nodes = buildNodeList(graph.getNodeCollection().getNode());
		this.nodeMap = extractNodes(this.nodes);		
	}
	
	

	/**
	 * Builds a map id-> node, for any node in the given list
	 * @param outerplanarNodeList the list to build the map
	 * @return a map id-> node, for any node in the given list
	 */
	private Map<String, OuterplanarNode> extractNodes(
			List<OuterplanarNode> outerplanarNodeList) {
		Map<String, OuterplanarNode> map = new HashMap<String, OuterplanarNode>();
		
		for (OuterplanarNode on : outerplanarNodeList)
			map.put(on.getId(), on);
		return map;
	}

	/**
	 * Builds a list with the "outerplanar version" of the nodes in the given list
	 * @param nodeTypeList a list with the nodes whereby the outerplanar version has to be built 
	 * @return a list with the "outerplanar version" of the nodes in the given list
	 */
	public List<OuterplanarNode> buildNodeList(List<NodeType> nodeTypeList) {
		
		List<OuterplanarNode> list = new LinkedList<OuterplanarNode>();
		Map<String, NodeType> nodeMap = Utility.extractNodes(this.graph);
		List<NodeType> boundary = Peeler.getBoundaryNodes(nodeTypeList, this.adjacencyMatrix, nodeMap);
		for (NodeType n : boundary)
			list.add(new OuterplanarNode(n, this.adjacencyMatrix.get(n.getId()).size()));
		
		return list;
	}

	/**
	 * @return the graph
	 */
	public GraphType getGraph() {
		return graph;
	}

	/**
	 * @param graph the graph to set
	 */
	public void setGraph(GraphType graph) {
		this.graph = graph;
	}

	/**
	 * @return the nodes
	 */
	public List<OuterplanarNode> getNodes() {
		return nodes;
	}

	/**
	 * @param nodes the nodes to set
	 */
	public void setNodes(List<OuterplanarNode> nodes) {
		this.nodes = nodes;
	}

	/**
	 * @return the nodeMap
	 */
	public Map<String, OuterplanarNode> getNodeMap() {
		return nodeMap;
	}

	/**
	 * @param nodeMap the nodeMap to set
	 */
	public void setNodeMap(Map<String, OuterplanarNode> nodeMap) {
		this.nodeMap = nodeMap;
	}

	/**
	 * @return the adjacencyMatrix
	 */
	public Map<String, Set<String>> getAdjacencyMatrix() {
		return adjacencyMatrix;
	}

	/**
	 * @param adjacencyMatrix the adjacencyMatrix to set
	 */
	public void setAdjacencyMatrix(Map<String, Set<String>> adjacencyMatrix) {
		this.adjacencyMatrix = adjacencyMatrix;
	}

}
